﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.ServiceModel;
using System.ServiceModel.DomainServices.Client;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Printing;
using System.Linq;


namespace AstekServis
{
    public static class WcfTimeoutUtility
    {
        /// <summary>
        /// Changes the WCF endpoint SendTimeout for the specified domain
        /// context. 
        /// </summary>
        /// <param name="context">The domain context to modify.</param>
        /// <param name="sendTimeout">The new timeout value.</param>
        public static void ChangeWcfSendTimeout(this DomainContext context,
                                                TimeSpan sendTimeout)
        {
            PropertyInfo channelFactoryProperty =
              context.DomainClient.GetType().GetProperty("ChannelFactory");
            if (channelFactoryProperty == null)
            {
                throw new InvalidOperationException(
                  "There is no 'ChannelFactory' property on the DomainClient.");
            }

            ChannelFactory factory = (ChannelFactory)
              channelFactoryProperty.GetValue(context.DomainClient, null);
            factory.Endpoint.Binding.SendTimeout = sendTimeout;
        }
    }

    //public static class PrintExtensions
    //{
    //    public static void Print(this FrameworkElement element, string Document, HorizontalAlignment HorizontalAlignment, VerticalAlignment VerticalAlignment, Thickness PageMargin, bool PrintLandscape, bool ShrinkToFit, Action OnPrintComplete)
    //    {
    //        Print(new List<FrameworkElement>() { element }, Document, HorizontalAlignment, VerticalAlignment, PageMargin, PrintLandscape, ShrinkToFit, OnPrintComplete);
    //    }

    //    public static void Print(this UIElementCollection elements, string Document, HorizontalAlignment HorizontalAlignment, VerticalAlignment VerticalAlignment, Thickness PageMargin, bool PrintLandscape, bool ShrinkToFit, Action OnPrintComplete)
    //    {
    //        Print(elements.ToList(), Document, HorizontalAlignment, VerticalAlignment, PageMargin, PrintLandscape, ShrinkToFit, OnPrintComplete);
    //    }

    //    public static void Print<T>(this List<T> elements, string Document, HorizontalAlignment HorizontalAlignment, VerticalAlignment VerticalAlignment, Thickness PageMargin, bool PrintLandscape, bool ShrinkToFit, Action OnPrintComplete)
    //    {
    //        PrintDocument printDocument = new PrintDocument();
    //        PageMargin = PageMargin == null ? new Thickness(10) : PageMargin;
    //        Document = (string.IsNullOrEmpty(Document)) ? "Print Document" : Document;
    //        int currentItemIndex = 0;
    //        printDocument.PrintPage += delegate(object sender, PrintPageEventArgs evt)
    //        {
    //            if (!typeof(FrameworkElement).IsAssignableFrom(elements[currentItemIndex].GetType()))
    //            {
    //                throw new Exception("Element must be an object inheriting from FrameworkElement");
    //            }

    //            FrameworkElement element = elements[currentItemIndex] as FrameworkElement;

    //            if (element.Parent == null || element.ActualWidth == double.NaN || element.ActualHeight == double.NaN)
    //            {
    //                throw new Exception("Element must be rendered, and must have a parent in order to print.");
    //            }

    //            TransformGroup transformGroup = new TransformGroup();

    //            //First move to middle of page...
    //            transformGroup.Children.Add(new TranslateTransform() { X = (evt.PrintableArea.Width - element.ActualWidth) / 2, Y = (evt.PrintableArea.Height - element.ActualHeight) / 2 });
    //            double scale = 1;
    //            if (PrintLandscape)
    //            {
    //                //Then, rotate around the center
    //                transformGroup.Children.Add(new RotateTransform() { Angle = 90, CenterX = evt.PrintableArea.Width / 2, CenterY = evt.PrintableArea.Height / 2 });

    //                if (ShrinkToFit)
    //                {
    //                    if ((element.ActualWidth + PageMargin.Left + PageMargin.Right) > evt.PrintableArea.Height)
    //                    {
    //                        scale = Math.Round(evt.PrintableArea.Height / (element.ActualWidth + PageMargin.Left + PageMargin.Right), 2);
    //                    }
    //                    if ((element.ActualHeight + PageMargin.Top + PageMargin.Bottom) > evt.PrintableArea.Width)
    //                    {
    //                        double scale2 = Math.Round(evt.PrintableArea.Width / (element.ActualHeight + PageMargin.Top + PageMargin.Bottom), 2);
    //                        scale = (scale2 < scale) ? scale2 : scale;
    //                    }
    //                }
    //            }
    //            else if (ShrinkToFit)
    //            {
    //                //Scale down to fit the page + margin

    //                if ((element.ActualWidth + PageMargin.Left + PageMargin.Right) > evt.PrintableArea.Width)
    //                {
    //                    scale = Math.Round(evt.PrintableArea.Width / (element.ActualWidth + PageMargin.Left + PageMargin.Right), 2);
    //                }
    //                if ((element.ActualHeight + PageMargin.Top + PageMargin.Bottom) > evt.PrintableArea.Height)
    //                {
    //                    double scale2 = Math.Round(evt.PrintableArea.Height / (element.ActualHeight + PageMargin.Top + PageMargin.Bottom), 2);
    //                    scale = (scale2 < scale) ? scale2 : scale;
    //                }
    //            }

    //            //Scale down to fit the page + margin
    //            if (scale != 1)
    //            {
    //                transformGroup.Children.Add(new ScaleTransform() { ScaleX = scale, ScaleY = scale, CenterX = evt.PrintableArea.Width / 2, CenterY = evt.PrintableArea.Height / 2 });
    //            }

    //            if (VerticalAlignment == VerticalAlignment.Top)
    //            {
    //                //Now move to Top
    //                if (PrintLandscape)
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = 0, Y = PageMargin.Top - (evt.PrintableArea.Height - (element.ActualWidth * scale)) / 2 });
    //                }
    //                else
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = 0, Y = PageMargin.Top - (evt.PrintableArea.Height - (element.ActualHeight * scale)) / 2 });
    //                }
    //            }
    //            else if (VerticalAlignment == VerticalAlignment.Bottom)
    //            {
    //                //Now move to Bottom
    //                if (PrintLandscape)
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = 0, Y = ((evt.PrintableArea.Height - (element.ActualWidth * scale)) / 2) - PageMargin.Bottom });
    //                }
    //                else
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = 0, Y = ((evt.PrintableArea.Height - (element.ActualHeight * scale)) / 2) - PageMargin.Bottom });
    //                }
    //            }

    //            if (HorizontalAlignment == HorizontalAlignment.Left)
    //            {
    //                //Now move to Left
    //                if (PrintLandscape)
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = PageMargin.Left - (evt.PrintableArea.Width - (element.ActualHeight * scale)) / 2, Y = 0 });
    //                }
    //                else
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = PageMargin.Left - (evt.PrintableArea.Width - (element.ActualWidth * scale)) / 2, Y = 0 });
    //                }
    //            }
    //            else if (HorizontalAlignment == HorizontalAlignment.Right)
    //            {
    //                //Now move to Right
    //                if (PrintLandscape)
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = ((evt.PrintableArea.Width - (element.ActualHeight * scale)) / 2) - PageMargin.Right, Y = 0 });
    //                }
    //                else
    //                {
    //                    transformGroup.Children.Add(new TranslateTransform() { X = ((evt.PrintableArea.Width - (element.ActualWidth * scale)) / 2) - PageMargin.Right, Y = 0 });
    //                }
    //            }

    //            evt.PageVisual = element;
    //            evt.PageVisual.RenderTransform = transformGroup;

    //            //Increment to next item,
    //            currentItemIndex++;

    //            //If the currentItemIndex is less than the number of elements, keep printing
    //            evt.HasMorePages = currentItemIndex < elements.Count;
    //        };

    //        printDocument.EndPrint += delegate(object sender, EndPrintEventArgs evt)
    //        {
    //            foreach (var item in elements)
    //            {
    //                FrameworkElement element = item as FrameworkElement;
    //                //Reset everything...
    //                TransformGroup transformGroup = new TransformGroup();
    //                transformGroup.Children.Add(new ScaleTransform() { ScaleX = 1, ScaleY = 1 });
    //                transformGroup.Children.Add(new RotateTransform() { Angle = 0 });
    //                transformGroup.Children.Add(new TranslateTransform() { X = 0, Y = 0 });
    //                element.RenderTransform = transformGroup;
    //            }

    //            //Callback to complete
    //            if (OnPrintComplete != null)
    //            {
    //                OnPrintComplete();
    //            }
    //        };

    //        printDocument.Print(Document);
    //    }
    //}

    public class PrintHelper
    {

        /// <summary>
        /// Prints a FrameworkElement in landscape, automatically rotating element if necessary
        /// </summary>
        /// <param name="DocumentName"></param>
        /// <param name="PrintableElement"></param>
        /// <param name="footerText"></param>
        public static void PrintElement(string DocumentName, FrameworkElement PrintableElement, string footerText)
        {
            PrintDocument p = new PrintDocument();
            Panel printableParent = PrintableElement.Parent as Panel;
            bool okToPrint = false;

            System.Windows.Controls.Panel tmp = new System.Windows.Controls.Canvas();

            p.BeginPrint += (object sender, BeginPrintEventArgs e) =>
            {
                ((Panel)PrintableElement.Parent).Children.Remove(PrintableElement);
                tmp.Children.Add(PrintableElement);
                tmp.Children.Add(new TextBlock
                {
                    VerticalAlignment = System.Windows.VerticalAlignment.Bottom,
                    Text = footerText,
                    FontSize = 8
                });
            };

            p.EndPrint += (s2, e2) =>
            {
                tmp.Children.Remove(PrintableElement);
                printableParent.Children.Add(PrintableElement);
                PrintableElement.HorizontalAlignment = HorizontalAlignment.Stretch;
                PrintableElement.VerticalAlignment = VerticalAlignment.Stretch;
                PrintableElement.Margin = new Thickness(0);
            };


            p.PrintPage += (object s, PrintPageEventArgs e) =>
            {

                // Rotate to landscape if necessary
                if (e.PrintableArea.Height > e.PrintableArea.Width)
                {
                    double scale = e.PrintableArea.Height / e.PrintableArea.Width;
                    scale = 1.0;

                    tmp.Width = e.PrintableArea.Height;
                    tmp.Height = e.PrintableArea.Width * scale;

                    CompositeTransform transform = new CompositeTransform
                    {
                        Rotation = 90,
                        TranslateX = tmp.Height * scale,
                        ScaleX = scale,
                        ScaleY = scale
                    };
                    tmp.RenderTransform = transform;
                    tmp.RenderTransformOrigin = new Point(0.5, 0.5);
                    PrintableElement.Margin = new Thickness(48 / scale, 96 / scale, 48 / scale, 0);
                    PrintableElement.Width = tmp.Width - 96 / scale;
                    PrintableElement.Height = tmp.Height - 96 / scale;

                }
                else
                {
                    tmp.Width = e.PrintableArea.Width;
                    tmp.Height = e.PrintableArea.Height;
                    PrintableElement.Margin = new Thickness(48, 96, 0, 0);
                    PrintableElement.Width = tmp.Width - 96;
                    PrintableElement.Height = tmp.Height - 96;
                }
                PrintableElement.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
                PrintableElement.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
                tmp.InvalidateArrange();
                tmp.InvalidateMeasure();
                okToPrint = true;

                if (okToPrint)
                {
                    e.PageVisual = tmp;
                    e.HasMorePages = false;
                }
                else
                {
                    e.PageVisual = null;
                    e.HasMorePages = true;
                }

            };
            p.Print(DocumentName);
        }

    }
}

namespace AstekServis.Bussiness
{
    public class Methods
    {
        private const char satirAyrac = '¤';
        private const char alanAyrac = '¥';
        private const char veriAyrac = '§';

        static CultureInfo provider = new CultureInfo("tr-TR");
        static object DefaultValue(string type)
        {
            switch (type)
            {
                case "System.String":
                    return string.Empty;
                case "System.Int32":
                    return 0;
                case "System.Int16":
                    return Convert.ToInt16(0);
                case "System.Int64":
                    return Convert.ToInt64(0);
                case "System.DateTime":
                    return DateTime.Now;
                case "System.Decimal":
                    return Convert.ToDecimal(0);
                case "System.Boolean":
                    return false;
                case "System.Double":
                    return Convert.ToDouble(0);
                case "System.Single":
                    return Convert.ToSingle(0);
                case "System.Byte":
                    return Convert.ToByte(0);
                default:
                    return null;
            }

        }
        public object[] CreateItemsSource(string data)
        {
            Type _RowClass;
            AssemblyName an = new AssemblyName("Result");
            System.Reflection.Emit.AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
            TypeBuilder tb = moduleBuilder.DefineType("RowType", TypeAttributes.Public |
                                                                                      TypeAttributes.Class |
                                                                                      TypeAttributes.AutoClass |
                                                                                      TypeAttributes.AnsiClass |
                                                                                      TypeAttributes.BeforeFieldInit |
                                                                                      TypeAttributes.AutoLayout
                                                                                      , typeof(object));

            ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

            string part1 = data.Substring(0, data.IndexOf(veriAyrac));
            string part2 = data.Substring(data.IndexOf(veriAyrac) + 1);
            string[] columns = part1.Split(satirAyrac);
            string[] rows = part2.Split(satirAyrac);

            for (int i = 0; i < columns.Length; i++)
            {
                string[] col = columns[i].Split(alanAyrac);
                string columnName = col[0];
                Type colType = Type.GetType(col[1]);

                FieldBuilder field = tb.DefineField(columnName, colType, FieldAttributes.Private);
                PropertyBuilder propBldr = tb.DefineProperty(columnName, System.Reflection.PropertyAttributes.HasDefault, colType, new Type[] { colType });

                MethodAttributes getSetAttr = MethodAttributes.Public;

                MethodBuilder getPropMthdBldr =
                    tb.DefineMethod("get_" + columnName,
                                               getSetAttr,
                                               colType,
                                                new Type[] { });
                ILGenerator custNameGetIL = getPropMthdBldr.GetILGenerator();

                custNameGetIL.Emit(OpCodes.Ldarg_0);
                custNameGetIL.Emit(OpCodes.Ldfld, field);
                custNameGetIL.Emit(OpCodes.Ret);

                MethodBuilder setPropMthdBldr =
                    tb.DefineMethod("set_" + columnName,
                                               getSetAttr,
                                               null,
                                               new Type[] { colType });
                ILGenerator custNameSetIL = setPropMthdBldr.GetILGenerator();

                custNameSetIL.Emit(OpCodes.Ldarg_0);
                custNameSetIL.Emit(OpCodes.Ldarg_1);
                custNameSetIL.Emit(OpCodes.Stfld, field);
                custNameSetIL.Emit(OpCodes.Ret);

                propBldr.SetGetMethod(getPropMthdBldr);
                propBldr.SetSetMethod(setPropMthdBldr);

            }
            _RowClass = tb.CreateType();

            object[] itemsSource = new object[rows.Length];
            for (int rowIdx = 0; rowIdx < rows.Length; rowIdx++)
            {
                object row = Activator.CreateInstance(_RowClass);

                for (int c = 0; c < columns.Length; c++)
                {
                    string[] col = columns[c].Split(alanAyrac);
                    string columnName = col[0];
                    Type colType = Type.GetType(col[1]);

                    PropertyInfo field = _RowClass.GetProperty(columnName);
                    object val = rows[rowIdx].Split(alanAyrac)[c];

                    field.SetValue(row, Convert.ChangeType(val, field.PropertyType, provider), null);
                }

                itemsSource[rowIdx] = row;
            }
            return itemsSource;
        }
    }
}
